package com.atguigu.juc.date930;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @Author: shenhao
 * @CreatTime: 2024/10/1 10:30
 * @Version: 1.0
 * 读写锁的一个具体案例, 在拥有写锁的时候,获取读锁,就能第一时间读取到自己修改的版本
 * 使用读锁后最后要释放,要不然会造成堵塞
 * 写线程首先获取写锁，更新数据，然后将锁降级为读锁。读线程在获取读锁后读取数据。
 *  * 这个过程演示了锁降级的概念，允许多个线程在持有读锁的情况下同时访问数据，
 *  * 提高了并发性能。`
 *  * 请注意，在锁降级期间，我们要确保数据的一致性，即在降级为读锁之前和之后都可以正确读取数据。
 *  * 这是锁降级的关键部分。（先获取读锁，再释放写锁）`
 */
public class LockDowngradingDemo {
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private final Lock readLock = lock.readLock();
    private final Lock writeLock = lock.writeLock();
    private int data = 0;

    public int readData(){
        readLock.lock();
        try {
            return data;
        } finally {
            readLock.unlock();
        }
    }

    public int updateData(int data){
        writeLock.lock();
        try {
            this.data=data;
            System.out.println("Data update to : "+data);
            // 自己写完了要获取读锁, 锁降级（先获取读锁，再释放写锁）
            readLock.lock();// 获取读锁
            System.out.println("Data read from : "+data);
        } finally {
            writeLock.unlock();
        }
        try {
            // 在持有读锁的情况下执行其他操作，读己之所写
            int currentData = this.data;
            System.out.println("current data : "+currentData);
            return currentData;
        }finally {
            readLock.unlock();
        }
    }

    public static void main(String[] args) {
        LockDowngradingDemo demo = new LockDowngradingDemo();
        new Thread(()->{
            System.out.println("自己读自己的结果:"+demo.updateData(50));
        }).start();

        new Thread(()->{
            System.out.println("其他线程读取到数据"+demo.readData());
        }).start();
    }
}
